//
//  request.swift
//  uiKit-demo
//
//  Created by 陈澎 on 2025/1/13.
//
import Foundation
import CommonCrypto

enum HTTPMethod: String {
    case GET
    case POST
}
enum NetworkError: Error {
    case invalidURL
    case responseError
    case decodingError
    case paramsError
}

enum UrlDomain: String{
    case search = "http://search-yxapp.beta1.fn"
}
struct RtResponse<T: Decodable>: Decodable {
    var body: T
//    var debug: [Any]
    let elapsedTime: Int?
    let errorCode: Int
    let errorDesc: String
    let logCode: String
    let success: Bool
}
struct RtResReturn<T> {
    var body: T
    let errorCode: Int
    let errorDesc: String
}

class NetworkManager {
    // 单例模式
    static let searchApi = NetworkManager(urlType: .search)
    private var baseUrl: String
    private let versionApi = "t170"
    private let version = "2.0.5"
    private init(urlType: UrlDomain) {
        self.baseUrl = urlType.rawValue
    }
    
    // 获取paramsMD5
    func getHmacsha256(messageStr: String) -> String? {
           // 获取 shakey
           let shakeyBase64 = "QHl4Nzg5KiZeREtKIyNDQw=="

           // Base64 解码 shakey
           guard let shakeyData = Data(base64Encoded: shakeyBase64),
                 let shakeyStr = String(data: shakeyData, encoding: .utf8) else {
               print("shakey Base64 解码失败")
               return nil
           }

           // HMAC-SHA256 计算
           guard let strData = messageStr.data(using: .utf8),
                 let keyData = shakeyStr.data(using: .utf8) else {
               print("字符串或密钥转换为 Data 失败")
               return nil
           }

           var hmac = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
           keyData.withUnsafeBytes { keyBytes in
               strData.withUnsafeBytes { strBytes in
                   guard let keyBaseAddress = keyBytes.baseAddress,
                         let strBaseAddress = strBytes.baseAddress else {
                       print("无法获取指针地址")
                       return
                   }
                   CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256),
                          keyBaseAddress, keyData.count,
                          strBaseAddress, strData.count,
                          &hmac)
               }
           }

           // 将 HMAC 结果转换为 Base64 字符串
           let hmacData = Data(hmac)
           return hmacData.base64EncodedString()
}
    func post<T: Decodable>(
        url: String,
        data: Any,
        header: [String: String] = [:],
        responseType: T.Type
    ) async throws -> RtResReturn<T> {
        var curHeader = header
        curHeader["Content-Type"] = "application/x-www-form-urlencoded"
        do {
            return try await self.request(urlString: url, method: HTTPMethod.POST, parameters: data, responseType: responseType)
        } catch {
            throw NetworkError.responseError
        }
    }
    
    /**
       发起网络请求
     - parameters·:
        - urlString: 请求地址
        - method: 请求方法
        - parameters：请求头
        - headers: 请求头
     - Returns: 返回解析后的数据
     */
    func request<T: Decodable>(
        urlString: String,
        method: HTTPMethod,
        parameters: Any,
        headers: [String: String]? = nil,
        responseType: T.Type
    ) async throws -> RtResReturn<T> {
        let urlStr = self.baseUrl + urlString + "/" + versionApi
       
        // 确保url有效
        guard let url = URL(string: urlStr) else {
            throw NetworkError.invalidURL
        }

        print("请求地址：\(urlStr)")
        // 构建urlRequest
        var request = URLRequest(url: url)
        
        // 请求方法
        request.httpMethod = method.rawValue
        
        // 设置请求头
        headers?.forEach { key, value in
            request.setValue(value, forHTTPHeaderField: key)
        }
        
        let bodyParamsData = [
            "isLoading":true,
            "version":version,
            "apiVersion":versionApi,
            "appVersion":version,
            "areaCode":"CS000016",
            "channel":"beta",
            "clientid":"a7ea53059fc868e2e3e2dd7c04027035",
            "device_id":"udid-Ka8n4ZOoI6xS",
            "time": Int(Date().timeIntervalSince1970 * 1000),
            "reRule":"4",
            "token":"e78d18702b8d536681cc0e8f2fb19a49",
            "source":"",
            "viewSize":"720x1184",
            "networkType":"wifi",
            "isSimulator":"false",
            "osType":"4",
            "body": parameters,
            "scopeType":1,
            "businessType":1,
            "businessId":"40080001",
            "deliveryCircleType":"3",
            "dockCode":"ZD4008"
        ]
        let bodyData = try JSONSerialization.data(withJSONObject: bodyParamsData, options: [])
      
        guard let str = String.init(data: bodyData, encoding: .utf8) else {
            throw NetworkError.paramsError
        }
        
        let md5MessageStr = str +
           "\(bodyParamsData["isSimulator"] ?? "")" +
           "\(bodyParamsData["viewSize"] ?? "")" +
           "\(bodyParamsData["networkType"] ?? "")" +
           "\(bodyParamsData["time"] ?? "")"
        
        // print("md5的内容: \(md5MessageStr)")
        guard let paramsMD5 = self.getHmacsha256(messageStr:md5MessageStr) else {
            throw NetworkError.paramsError
        }
       
        print("paramsMD5: \(paramsMD5)")
        
        let paramsDic: [String: Any] = [
            "data": str,
            "paramsMD5": paramsMD5
        ]

        //如果是post请求头 添加请求体
        if method == .POST {
            request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
//            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            // 将参数编码为键值对格式
//            let bodyJson = try JSONSerialization.data(withJSONObject: paramsDic, options: [])
            let bodyString = paramsDic.map {"\($0.key)=\($0.value)"}.joined(separator: "&")
            request.httpBody = bodyString.data(using: .utf8)
        }
        
        // 打印请求头信息
//        if let headers = request.allHTTPHeaderFields {
//            print("请求头:")
//            for (key, value) in headers {
//                print("\(key): \(value)")
//            }
//        } else {
//            print("No headers found in the request.")
//        }
        
        print("请求报文：\(String.init(data: request.httpBody!, encoding: .utf8) ?? "")")

        // 发起请求
        let (data, response) = try await URLSession.shared.data(for: request)
        print("返回信息：\(String(describing: String(data: data, encoding: .utf8)))")
        // 确保响应状态是2xx
        guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
            throw NetworkError.responseError
        }
        
        // 解析数据
        do {
            let responseType: RtResponse<T>.Type = RtResponse<T>.self
            let decodeData = try JSONDecoder().decode(responseType, from: data)
            return RtResReturn(body: decodeData.body, errorCode: decodeData.errorCode, errorDesc: decodeData.errorDesc)
        } catch {
            print("decode失败：\(error)")
            throw NetworkError.decodingError
        }
    }
}
